package at.jku.cp.mir.data;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

/**
 * This implementation of a {@link DataFetcher} gets first all top tracks for a
 * given artist and then stores all top tags for each track into a separate
 * file.
 * @author clemens
 */
public class ArtistTopTrackTagsFetcher extends DataFetcher
{

	// maximum number of top tracks
	private static final int NR_OF_TOP_TRACKS = 10;

	// directory, where the subfolders for each artist shall be created
	private final File destinationDir;
	private final SAXBuilder xmlBuilder;
	private final XPath trackXPath;

	public ArtistTopTrackTagsFetcher(File artistFile, File destinationDir)
	{
		super(artistFile);
		this.destinationDir = destinationDir;

		xmlBuilder = new SAXBuilder();
		try
		{
			trackXPath = XPath.newInstance("//track/name");
		} catch (JDOMException e)
		{
			throw new RuntimeException("invalid XPath", e);
		}
	}

	@Override
	protected boolean fetchData(String artist, String lastFmArtist)
	{
		// create the directory, where all top tags for each track shall be
		// stored to
		File artistDir = new File(destinationDir, getFileConformName(artist));
		if (artistDir.exists())
		{
			System.out.println("skipping top track tags for artist '" + lastFmArtist + "'");
			return false;
		}
		artistDir.mkdirs();

		// first get the top tracks for this artist
		byte[] topTracksContent;
		try
		{
			topTracksContent = communicator.downloadArtistTopTracks(lastFmArtist);
		} catch (IOException e)
		{
			throw new IllegalStateException("exception while downloading top tracks for artist '" + lastFmArtist + "'",
					e);
		}

		List<Element> trackElements = null;
		try
		{
			// parse the top tracks document
			Document topTracksDoc = xmlBuilder.build(new ByteArrayInputStream(topTracksContent));

			// get a list of all top tracks
			trackElements = trackXPath.selectNodes(topTracksDoc);
		} catch (JDOMException e)
		{
			throw new IllegalStateException("exception while parsing topTracks xml document", e);
		} catch (IOException e)
		{
			throw new IllegalStateException("exception while parsing topTracks xml document", e);
		}

		// adjust the number of top tracks
		int min = Math.min(NR_OF_TOP_TRACKS, trackElements.size());
		trackElements = trackElements.subList(0, min);

		// get the top tags for each track
		int currentTrackIndex = 0;
		for (Element trackElement : trackElements)
		{
			String trackName = trackElement.getTextTrim();
			try
			{
				byte[] topTagsContent = super.communicator.downloadTrackTopTags(lastFmArtist, trackName);

				// assembly the top track tags file name and increase the
				// current track index
				String fileName = "track_" + currentTrackIndex + ".xml";
				currentTrackIndex++;

				File topTagFile = new File(artistDir, fileName);
				saveData(topTagsContent, topTagFile);
			} catch (IOException e)
			{
				throw new IllegalStateException("exception while downloading top tags for track '" + trackName
						+ "' for artist '" + lastFmArtist + "'", e);
			}
		}

		System.out.println("fetched track top tags for artist '" + lastFmArtist + "'");
		return true;
	}

}
